#!/usr/local/bin/python

import socket
from binascii import b2a_hex, a2b_hex
import array
from random import randint
from time import sleep
import tcp

def dec2hex(n):
    return "%02X" % n

def hex2dec(n):
    return int(s, 16)

def construyeBarras():
    nBarras = 97
    posBarra = {}
    for n in range(nBarras):
        posBarra[n] = 48
    posBarra[29] = posBarra[76] = 0
    posBarra[35] = posBarra[61] = 8
    posBarra[57] = 12
    posBarra[39] = 14

    nBarraSeleccionada = -1
    return (posBarra, nBarraSeleccionada)
    
def construyeMensaje(posBarra, nBarraSeleccionada):
    # Construimos un array de bytes con signo
    msg = array.array('b')

    # Cabecera del mensaje
    nBarras = len(posBarra)
    msg.insert(0, nBarras + 1)
    msg.insert(1, 0)

    # A partir de aqui entra en el byte de comprobacion
    msg.insert(2, nBarraSeleccionada)
    suma = nBarraSeleccionada

    # Posicion de cada barra
    for n in range(nBarras):
        msg.append(posBarra[n])
        suma = suma + posBarra[n]
  
    # byte de comprobacion
    check = suma & 0xFF
    msg.append(check)
    return msg

def muestraMensaje(msg):
    st = msg.tostring()
    for bt in st:
        print dec2hex(ord(bt)),
    print ''

def peticionValida(canal):
    data = canal.recv(1024)
    return len(data) == 2 and ord(data[0]) == 0x1F and ord(data[1]) == 0x1F

def enviaRespuesta(canal):
    global msg

    # Simulamos el MBC real, que puede partir la respuesta en bloques
    # no siempre lo dividimos...
    if randint(0,1) == 0:
       canal.send(msg.tostring())
    else:
    # ... cuando lo dividimos, lo hacemos en dos segmentos
       nBytes = len(msg)
       n = randint(1, nBytes-1)
       canal.send(msg[:n].tostring())
       sleep(0.25)
       canal.send(msg[n:].tostring())

def checkCorrecto(datos):
    suma = 0
    for c in datos[2:-1]:
        suma = suma + ord(c)
    checkCalculado = suma & 0xFF
    checkRecibido = ord(datos[-1:].tostring())
    return checkCalculado == checkRecibido

def formatoCorrecto(datos):
    nBarras = len(datos) - 4

    b0Esperado = nBarras + 1
    b1Esperado = 0x00

    b0Recibido = ord(datos[0])
    b1Recibido = ord(datos[1])
    
    return b0Esperado == b0Recibido and b1Esperado == b1Recibido and checkCorrecto(datos)

def procesaRespuesta(datos):
    data = array.array('b')
    data.fromlist(datos.tolist())
    posBarras = data[3:-1].tolist()
    print posBarras[0:2]

    
def estableceConexion(host, port):
    # Creamos un socket para TCP
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # Conectamos con el servidor
    s.connect((host, port))
    print "Conectado"
    return s

def gestionaComunicacion(host, port, nBarras):
    s = estableceConexion(host, port)
    nBytesEsperados = 2 + 1 + nBarras + 1
    while 1:
       # Enviamos peticion
       s.send('\x1F\x1F')
       # Leemos respuesta
       (datos, nBytesRecibidos) = tcp.tcp_read_wait(s, nBytesEsperados, 2)
       if nBytesRecibidos == nBytesEsperados and formatoCorrecto(datos):
          procesaRespuesta(datos)
          print "OK"
       else:
          # Cerramos el socket, salimos de la funcion y volvemos a empezar
          break
       # Esperamos a repetir el ciclo
       sleep(4)

    s.close()
    print "Desconectado"


host = "127.0.0.1"
port = 5001
nBarras = 97
while 1:
    gestionaComunicacion(host, port, nBarras)



